package com.cccyy.encry.sm4;

import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

public class SM4Example {
    public static void main(String[] args) {
        try {
            // === 第一阶段：密钥生成 ===
            System.out.println("=== SM4密钥生成 ===");
            byte[] key = generateSM4Key();
            System.out.println("SM4密钥生成完成，密钥长度: " + key.length + " 字节");

            // === 第二阶段：数据加密 ===
            System.out.println("\n=== 数据加密 ===");
            String plaintext = "这是需要加密的机密信息：银行账户密码123456";
            byte[] encrypted = encryptSM4(plaintext.getBytes("UTF-8"), key);
            System.out.println("原始数据: " + plaintext);
            System.out.println("加密完成，密文长度: " + encrypted.length + " 字节");
            System.out.println("密文(Base64): " + Base64.getEncoder().encodeToString(encrypted));

            // === 第三阶段：数据解密 ===
            System.out.println("\n=== 数据解密 ===");
            byte[] decrypted = decryptSM4(encrypted, key);
            String decryptedText = new String(decrypted, "UTF-8");
            System.out.println("解密结果: " + decryptedText);
            System.out.println("解密成功: " + plaintext.equals(decryptedText));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 生成SM4密钥
    private static byte[] generateSM4Key() {
        byte[] key = new byte[16]; // SM4使用128位（16字节）密钥
        new SecureRandom().nextBytes(key);
        return key;
    }

    // SM4加密
    private static byte[] encryptSM4(byte[] plaintext, byte[] key) {
        try {
            SM4Engine engine = new SM4Engine();
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(engine));

            // 初始化加密器
            cipher.init(true, new KeyParameter(key));

            // 执行加密
            byte[] output = new byte[cipher.getOutputSize(plaintext.length)];
            int len = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
            len += cipher.doFinal(output, len);

            // 返回实际长度的数组
            return Arrays.copyOf(output, len);
        } catch (Exception e) {
            throw new RuntimeException("SM4加密失败", e);
        }
    }

    // SM4解密
    private static byte[] decryptSM4(byte[] ciphertext, byte[] key) {
        try {
            SM4Engine engine = new SM4Engine();
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(engine));

            // 初始化解密器
            cipher.init(false, new KeyParameter(key));

            // 执行解密
            byte[] output = new byte[cipher.getOutputSize(ciphertext.length)];
            int len = cipher.processBytes(ciphertext, 0, ciphertext.length, output, 0);
            len += cipher.doFinal(output, len);

            // 返回实际长度的数组
            return Arrays.copyOf(output, len);
        } catch (Exception e) {
            throw new RuntimeException("SM4解密失败", e);
        }
    }
}